
package uk.addie.mp3fixer.widget;

import java.awt.GridLayout;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.nio.file.Path;

import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import uk.addie.mp3fixer.FileSystemList;
import uk.addie.mp3fixer.FileSystemList.AlbumList;
import uk.addie.mp3fixer.FileSystemList.TrackList;
import uk.addie.mp3fixer.MP3Fixer;
import uk.addie.mp3fixer.MP3Handle;

public class FileSelectorWidget extends JPanel {
    private static final String FOCUS            = "focus";
    private static final long   serialVersionUID = 1L;

    protected static boolean isWidgetCleared(final JList<String> widget) {
        return widget.getSelectedIndex() == -1;
    }

    protected static void selectFirst(final JList<String> widget) {
        widget.clearSelection();
        widget.setSelectedIndex(0);
    }

    protected FileSystemList      mArtistList;
    protected AlbumList           mAlbumList;
    protected TrackList           mTrackList;
    protected JList<String>       mArtistListWidget;
    protected JList<String>       mAlbumListWidget;
    protected JList<String>       mTrackListWidget;
    protected final MP3InfoWidget mp3info;

    public FileSelectorWidget(final MP3InfoWidget mp3info) {
        super();
        setLayout(new GridLayout());
        addArtistToFrame();
        addAlbumToFrame();
        addTracklistToFrame();
        this.mp3info = mp3info;
    }

    private void addAlbumToFrame() {
        mAlbumList = new FileSystemList.AlbumList();
        mAlbumListWidget = new JList<>(mAlbumList);
        mAlbumListWidget.addListSelectionListener(new ListSelectionListener() {
            @Override public void valueChanged(final ListSelectionEvent e) {
                if (!e.getValueIsAdjusting() && !isWidgetCleared(mAlbumListWidget)) {
                    final String artist = getArtist();
                    final String album = getAlbum();
                    mp3info.clear();
                    mTrackListWidget.clearSelection();
                    mTrackList.setAlbum(artist, album);
                    selectFirst(mTrackListWidget);
                }
            }
        });
        mAlbumListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK), "selectPreviousRow");
        mAlbumListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK), "selectNextRow");
        mAlbumListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_2, InputEvent.ALT_DOWN_MASK), FOCUS);
        mAlbumListWidget.getActionMap().put(FOCUS, new FocusAction(mAlbumListWidget));
        add(new JScrollPane(mAlbumListWidget));
    }

    private void addArtistToFrame() {
        mArtistList = new FileSystemList.ArtistList();
        mArtistListWidget = new JList<>(mArtistList);
        mArtistListWidget.addListSelectionListener(new ListSelectionListener() {
            @Override public void valueChanged(final ListSelectionEvent e) {
                if (!e.getValueIsAdjusting() && !isWidgetCleared(mArtistListWidget)) {
                    final String artist = getArtist();
                    mp3info.clear();
                    mTrackList.clear();
                    mAlbumList.changeArtist(artist);
                    selectFirst(mAlbumListWidget);
                }
            }
        });
        mArtistListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_1, InputEvent.ALT_DOWN_MASK), FOCUS);
        mArtistListWidget.getActionMap().put(FOCUS, new FocusAction(mArtistListWidget));
        add(new JScrollPane(mArtistListWidget));
    }

    private void addTracklistToFrame() {
        mTrackList = new FileSystemList.TrackList();
        mTrackListWidget = new JList<>(mTrackList);
        mTrackListWidget.addListSelectionListener(new ListSelectionListener() {
            @Override public void valueChanged(final ListSelectionEvent e) {
                if (!e.getValueIsAdjusting() && !isWidgetCleared(mTrackListWidget)) {
                    final String track = getTrack();
                    final Path path = MP3Fixer.getRoot().resolve(getArtist()).resolve(getAlbum()).resolve(track);
                    final MP3Handle mp3 = MP3Handle.withPath(path);
                    mp3info.setMP3(mp3);
                }
            }
        });
        mTrackListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK), "selectPreviousRow");
        mTrackListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK), "selectNextRow");
        mTrackListWidget.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_3, InputEvent.ALT_DOWN_MASK), FOCUS);
        mTrackListWidget.getActionMap().put(FOCUS, new FocusAction(mTrackListWidget));
        add(new JScrollPane(mTrackListWidget));
    }

    public String getAlbum() {
        final int index = mAlbumListWidget.getSelectedIndex();
        return mAlbumList.getElementAt(index);
    }

    public String getArtist() {
        final int index = mArtistListWidget.getSelectedIndex();
        return mArtistList.getElementAt(index);
    }

    public String getTrack() {
        final int index = mTrackListWidget.getSelectedIndex();
        return mTrackList.getElementAt(index);
    }

    public void refresh() {
        if (mArtistList.getPath().equals(MP3Fixer.getRoot())) {
            mTrackList.refresh();
            mAlbumList.refresh();
            mArtistList.refresh();
        } else {
            mArtistList.setPath(MP3Fixer.getRoot());
            mAlbumList.setPath(null);
            mTrackList.setPath(null);
            mp3info.clear();
        }
    }

    @Override public String toString() {
        return new StringBuilder().append(getArtist()).append(getAlbum()).append(getTrack()).toString();
    }
}
